<?php

namespace app\lib;

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use think\facade\Cache;
use think\facade\Config;

class ChinaMobileSMS
{
    private $conf;

    public function __construct()
    {
        $this->conf = Config::get('chinaMobile');
    }

    /**
     * 发送消息
     * @param $mobile 号码
     * @param string $prefix 用处
     */
    public function send($mobile, $prefix = 'regist'): bool
    {
        $code = $this->randCode();
        $cache = $this->cache($mobile, $code, $prefix, true);
        if ($cache == false)
            return $cache;
        $response = $this->client()->post($this->conf['url'], [
            [
                RequestOptions::BODY => [
                    'ecName' => $this->conf['ec_name'],
                    'apId' => $this->conf['ap_id'],
                    'templateId' => $this->conf['template_id'],
                    'mobiles' => $mobile,
                    'params' => '["' . $code . '"]',
                    'sign' => $this->conf['sign'],
                    'addSerial' => $this->conf['add_serial'],
                    'mac' => $this->mac($mobile, $code)
                ]
            ]
        ]);
        $callback = json_decode($response->getBody()->getContents(), true);
        return $callback['success'];
    }

    /**
     * 验证消息
     * @param $mobile 号码
     * @param string $prefix 用处
     */
    public function check($mobile, $code, $prefix = 'regist'): bool
    {
        return $this->cache($mobile, $code, $prefix);
    }

    private function cache($mobile, $code, $prefix = 'regist', $set = false): bool
    {
        $key = 'cm:' . $prefix . ':' . $mobile;
        if ($set) {
            return Cache::set($key, $code, $this->conf['expire']);
        } else {
            return Cache::get($key) == $code;
        }
    }

    private function randCode(): string
    {
        $password = $tmp = '';
        while (strlen($password) < $this->conf['length']) {
            $tmp = substr($this->conf['chars'], mt_rand(0, strlen($this->conf['chars'])), 1);
            $password .= $tmp;
        }
        return $password;
    }

    private function client(): Client
    {
        return new Client(['verify' => false, 'content-type' => 'application/json']);
    }

    /**
     * 生成校验
     * @param $mobile 号码
     * @param $code 验证码
     */
    private function mac($mobile, $code): string
    {
        return md5($this->conf['ec_name'] . $this->conf['ap_id'] . $this->conf['secret_key'] . $this->conf['template_id'] . $mobile . '["' . $code . '"]' . $this->conf['sign'] . $this->conf['add_serial']);
    }
}